--
-- Author: shunguo.chen
-- Date: 2016-06-21 20:39:27
--
-- 时间相关，全局函数

local TimeUtil = {}

local secondsOfDay = 24 * 60 * 60

-- interval:单位秒，0表示每帧调用
-- loop:0表示无限循环，正整数为相应次数
local scheduler = cc.Director:getInstance():getScheduler()
function TimeUtil.setSchedule(handler, interval, loop, onComplete, paused)
    interval = interval or 0
    loop = loop or 0
    paused = paused or false

    local handler_interval = (0 == interval) and cc.Director:getInstance():getAnimationInterval() or interval
    local data = {paused = paused, curTime = 0, loop = loop, interval = handler_interval}
    local scheduleID = nil
    scheduleID = scheduler:scheduleScriptFunc(function(dt)
        if not data.paused then
            data.curTime = data.curTime + 1
            data.dt = dt
            if data.curTime == data.loop then
                scheduler:unscheduleScriptEntry(scheduleID)
                if nil ~= handler then
                    handler(data)
                end
                if nil ~= onComplete then
                    onComplete()
                end
            else
                if nil ~= handler then
                    handler(data)
                else
                    scheduler:unscheduleScriptEntry(scheduleID)
                end
            end
        end
    end, interval, false)
    data.id = scheduleID
    return data
end
function TimeUtil.pauseSchedule(data)
    if nil ~= data then
        data.paused = true
    end
end
function TimeUtil.resumeSchedule(data)
    if nil ~= data then
        data.paused = false
    end
end
function TimeUtil.resetSchedule(data, curTime, loop)
    if nil ~= data then
        loop = loop or 0
        data.curTime = curTime
        data.loop = loop
    end
end
function TimeUtil.clearSchedule(data)
    if nil ~= data and nil ~= data.id then
        scheduler:unscheduleScriptEntry(data.id)
    end
end

function TimeUtil.scheduleWithNode(node, callback, delay)
    local delay = cc.DelayTime:create(delay)
    local sequence = cc.Sequence:create(delay, cc.CallFunc:create(callback))
    local action = cc.RepeatForever:create(sequence)
    node:runAction(action)
    return action
end

function TimeUtil.delayWithNode(node, callback, delay)
    local delay = cc.DelayTime:create(delay or 0)
    local sequence = cc.Sequence:create(delay, cc.CallFunc:create(callback))
    node:runAction(sequence)
    return sequence
end

-- 01:02:03 转 秒
-- 15:00    转 秒
function TimeUtil.timeToSeconds(time)
    local hour, min, sec = string.match(time, "(%d+):(%d+):(%d+)")
    if hour == nil then
        hour = 0
        min, sec = string.match(time, "(%d+):(%d+)")
    end
    hour = tonumber(hour)
    min = tonumber(min)
    sec = tonumber(sec)
    if hour == nil or min == nil or sec == nil then return 0 end
    return hour * 3600 + min * 60 + sec
end

--秒变 01：02:03 或 02:03
function TimeUtil.secondsToTime(seconds)
    if seconds < 0 then seconds = 0 end
    local h = math.floor(seconds / 3600)
    local m = math.floor(seconds % 3600 / 60)
    local s = (seconds % 3600) % 60
    local h_str = (h < 10) and "0"..h or tostring(h)
    local m_str = (m < 10) and "0"..m or tostring(m)
    local s_str = (s < 10) and "0"..s or tostring(s)
    if h > 0 then
        return h_str..":"..m_str..":"..s_str
    else
        return m_str..":"..s_str
    end
end

--秒转字符串
--type=1, return 4(天), "01:00:00"
--type=2
--      >1天 return {day},gap
--      <=1天 return {h,m,s},1
--type=3, return {h,m,s}
function TimeUtil.secondsToStr(seconds, type)
    if seconds < 0 then seconds = 0 end
    local h = math.floor(seconds / 3600)
    local m = math.floor(seconds % 3600 / 60)
    local s = math.floor((seconds % 3600) % 60)
    if type == 1 then
        local h_str = (h < 10) and "0"..h or tostring(h)
        local m_str = (m < 10) and "0"..m or tostring(m)
        local s_str = (s < 10) and "0"..s or tostring(s)

        local day = math.floor(h / 24)
        h = h % 24
        h_str = h < 10 and "0"..h or tostring(h)
        return day, h_str..":"..m_str..":"..s_str
    elseif type == 2 then
        local day = math.floor(seconds / 86400)
        if day >= 1 then
            local gap = seconds % 86400
            return {day}, gap
        else
            return {h,m,s}, 1
        end
    elseif type == 3 then
        return {h,m,s}
    elseif type == 4 then
        local day = math.floor(seconds / 86400)
        h = h % 24
        local show_day = nil
        local show_hour = nil
        local show_min = nil
        if day > 0 then
            show_day = day
            if h > 0 then
                show_hour = h
            elseif m > 0 then
                show_min = m
            elseif s > 0 then
                show_min = 1
            end
        else
            if h > 0 then
                show_hour = h
                if m > 0 then
                    show_min = m
                elseif s > 0 then
                    show_min = 1
                end
            else
                if m > 0 then
                    show_min = m
                elseif s > 0 then
                    show_min = 1
                end
            end
        end
        if show_day and show_day > 999 then
            return nil
        end 
        return {show_day, show_hour, show_min}
    end
end

-- timestamp 时间搓
-- rangeStr 范围string 这里是 11:30-13:00
-- return -1(在前面) 0(在范围内) 0(在后面)
function TimeUtil.checkTimeInRange(timestamp, rangeStr)
    local startHour, startMin, endHour, endMin = string.match(rangeStr, "(%d+):(%d+)-(%d+):(%d+)")
    local startSeconds = startHour * 3600 + startMin * 60
    local endSeconds = endHour * 3600 + endMin * 60
    local date = os.date("*t", timestamp)
    local daySeconds = date.day * 3600 + date.min * 60 + date.sec
    if daySeconds >= startSeconds and daySeconds <= endSeconds then
        return 0
    elseif daySeconds < startSeconds then
        return -1
    else
        return 1
    end
end

-- 时间相关的字符串的时区转换 11:30-13:00 -》 12:30-12:00
-- timeStr 范围string 这里是 11:30-13:00
-- zoneOffset 时区偏移
function TimeUtil.convertTimeStrByTimeZone(timeStr, zoneOffset)
    local ret = string.gsub(timeStr, "(%d+):", function(num)
        num = tonumber(num) + zoneOffset
        if num >= 24 then
            num = num - 24
        elseif num < 0 then
            num = num + 24
        end
        return num .. ":"
    end)
    return ret
end

function TimeUtil.secondsToDate(seconds)
    local date = os.date("%Y-%m-%d", math.floor(seconds))
    local hour = os.date("%H:%M", math.floor(seconds))
    return {date,hour}
end

function TimeUtil:deltaSecondsToTime(ds)
    local ret = {}
    ret.d = math.floor(ds/86400)
    ret.h = math.floor(math.fmod(ds, 86400)/3600)
    ret.m = math.floor(math.fmod(ds, 3600)/60)
    ret.s = math.floor(math.fmod(ds, 60))
    
    return ret
end

function TimeUtil:deltaSecondsToTimeString(ds)
    local r = self:deltaSecondsToTime(ds)
    if r.d > 0 then
        return string.format(L("countdowen_day"), tostring(r.d))..string.format(L("countdowen_hour"), tostring(r.h))
    elseif r.h > 0 then
        return string.format(L("countdowen_hour"), tostring(r.h))..string.format(L("countdowen_min"), tostring(r.m))
    elseif r.m > 0 then
        return string.format(L("countdowen_min"), tostring(r.m))
    else
        return string.format(L("countdowen_min"), "1")
    end
    return ""
end

-- 获取当前时间所在周 指定时间 的时间戳
function TimeUtil.getTargetTimeStamp( wday, hour, min, sec ) -- wday = sunday=1
    if not wday then return end
    hour = tonumber( hour or 0 )
    min = tonumber( min or 0 )
    sec = tonumber( sec or 0 )

    -- print( " ----------->>>>> getTargetTimeStamp ", wday, hour )

    local curTime = math.floor(app.session:getServerTime() or app:getTime())
    local curDate = os.date("*t", curTime)
    -- for i,v in pairs( curDate ) do
    --     print( " ----------->>>> cur ", i , v )
    -- end

    local dayOffset = 0 -- 天数差值
    if curDate.wday ~= wday then -- 非同一天？存在差值
        if 1 == wday then -- 周日？
            dayOffset = ( wday + 7 ) - curDate.wday
        else
            dayOffset = wday - curDate.wday
        end
    end
    -- print( " ----------->>>>> dayOffset ", dayOffset )

    local afterTime = curTime + secondsOfDay * dayOffset
    local afterDate = os.date("*t", afterTime)

    afterDate.hour = hour
    afterDate.min = min
    afterDate.sec = sec
    -- for i,v in pairs( afterDate ) do
    --     print( " ----------->>>> after " , i , v )
    -- end

    return os.time( afterDate )
end

-- 获取当天 指定时间 的时间戳
function TimeUtil.getCurDayTargetTimeStamp(hour, min, sec)
    local serverTime = app.session:getServerTime() or os.time()
    local timeData = os.date("*t", serverTime)
    local weekDay = timeData.wday --取值1-7，1是周日
    return TimeUtil.getTargetTimeStamp(weekDay, hour, min, sec)
end

-- 获取指定时间的下一次时间戳
function TimeUtil.getNextTargetTimeStamp(seconds)
    if not seconds then return end
    local hour = math.floor(seconds / 3600)
    local min = math.floor(seconds % 3600 / 60)
    local serverTime = app.session:getServerTime() or os.time()
    local timeData = os.date("*t", serverTime)
    local interval = 0
    if timeData.hour < hour or (timeData.hour == hour and timeData.min < min) then
        -- 下一次时间戳在今天
        interval = 0
    else
        -- 下一次时间戳在明天
        interval = 24*3600
    end
    timeData.hour = hour
    timeData.min = min
    return os.time(timeData) + interval
end

-- 根据年月日获取周几
function TimeUtil.getWeekByYearMonthDay(y, m, d)
    local weekNum
    local time = os.time({year = tostring(y), month = tostring(m), day = tostring(d)})
    local weekNum = os.date("*t", time).wday - 1
    if weekNum == 0 then
        weekNum = 7
    end
    return weekNum
end

return TimeUtil
